#pragma once

#include <exception>
using namespace std;

#include "unorderedListNode.h"

namespace uppg4
{
	class unorderedList
	{
	private:
		unorderedListNode* head;
		unorderedListNode* tail;
		unorderedListNode* freehead;

		class iterator
		{
		private:
			unorderedListNode* n;
		public:
			iterator()
			{
				n = nullptr;
			}

			iterator(unorderedListNode* n)
			{
				this->n = n;
			}

			iterator & operator++(int)
			{
				if (n == nullptr)
				{
					throw exception("out of bounds");
				}
				else
				{
					n = n->next;
				}
				return *this;
			}

			bool operator== (iterator& i)
			{
				return n == i.n;
			}

			unorderedListNode & operator*()
			{
				return *n;
			}

			unorderedListNode * operator->()
			{
				return n;
			}
		};

	public:

		unorderedList()
		{
			head = nullptr;
			tail = nullptr;
			freehead = nullptr;
		}

		unorderedList(int freelistSize)
		{
			head = nullptr;
			tail = nullptr;
			freehead = nullptr;

			for (int i = 0; i < freelistSize; i++)
			{
				unorderedListNode* n = new unorderedListNode();
				n->next = freehead;
				freehead = n;
			}
		}

		~unorderedList()
		{
			while (head != nullptr)
			{
				unorderedListNode* n = head->next;
				delete head;
				head = n;
			}

			while (freehead != nullptr)
			{
				unorderedListNode* n = freehead->next;
				delete freehead;
				freehead = n;
			}
		}

		void add(string data)
		{
			//skapa nod
			unorderedListNode* n;
			if (freehead != nullptr)
			{
				n = freehead;
				freehead = freehead->next;
				n->data = data;
			}
			else
			{
				n = new unorderedListNode(data);
			}

			if (head == nullptr)
			{
				head = tail = n;
			}
			else if (head == tail)
			{
				head->next = tail = n;
			}
			else
			{
				tail->next = n;
				tail = tail->next;
			}
		}

		void deleteHeader()
		{
			if (head == nullptr)
			{
				throw exception("list is empty!");
			}
			else
			{
				unorderedListNode *n = head;
				head = head->next;
				n->data = "";
				n->next = freehead;
				freehead = n;
			}			
		}

		void clear()
		{
			while (head != nullptr)
			{
				unorderedListNode *n = head;
				head = head->next;
				n->data = "";
				n->next = freehead;
				freehead = n;
			}
		}

		void print()
		{
			unorderedListNode *n = head;
			while (n != nullptr)
			{
				cout << n->data << endl;
				n = n->next;
			}
		}

		iterator begin()
		{
			return iterator(head);
		}

		iterator end()
		{
			return iterator();
		}
	};
}